package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"

	"new_sensitive/internal/ac"
	"new_sensitive/internal/api"
	"new_sensitive/internal/storage"
)

// Config 配置结构体
type Config struct {
	Database struct {
		Host     string `json:"host"`
		Port     int    `json:"port"`
		Username string `json:"username"`
		Password string `json:"password"`
		DBName   string `json:"dbname"`
		Charset  string `json:"charset"`
	} `json:"database"`

	Server struct {
		Port           int `json:"port"`
		UpdateInterval int `json:"update_interval"`
	} `json:"server"`

	Log struct {
		Level string `json:"level"`
		File  string `json:"file"`
	} `json:"log"`

	Redis struct {
		Host     string `json:"host"`
		Port     int    `json:"port"`
		Password string `json:"password"`
		DB       int    `json:"db"`
	} `json:"redis"`
}

var (
	configFile string
	config     Config
)

// init 初始化函数
func init() {
	// 解析命令行参数
	flag.StringVar(&configFile, "config", "config.json", "配置文件路径")
	flag.Parse()

	// 读取配置文件
	data, err := os.ReadFile(configFile)
	if err != nil {
		log.Fatalf("读取配置文件失败: %v", err)
	}

	// 解析配置文件
	if err := json.Unmarshal(data, &config); err != nil {
		log.Fatalf("解析配置文件失败: %v", err)
	}
}

func main() {
	// 初始化日志系统
	logFile := config.Log.File
	// 确保日志目录存在
	if err := os.MkdirAll(filepath.Dir(logFile), 0755); err != nil {
		log.Fatalf("创建日志目录失败: %v", err)
	}
	// 打开日志文件
	f, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("打开日志文件失败: %v", err)
	}
	defer f.Close()
	log.SetOutput(f)

	// 初始化数据库连接
	db, err := storage.NewMySQLStorage(
		config.Database.Host,
		config.Database.Port,
		config.Database.Username,
		config.Database.Password,
		config.Database.DBName,
		config.Database.Charset,
	)
	if err != nil {
		log.Fatalf("初始化数据库连接失败: %v", err)
	}
	defer db.Close()

	// 初始化Redis连接
	redis, err := storage.NewRedisStorage(
		config.Redis.Host,
		config.Redis.Port,
		config.Redis.Password,
		config.Redis.DB,
	)
	if err != nil {
		log.Fatalf("初始化Redis连接失败: %v", err)
	}
	defer redis.Close()

	// 初始化AC自动机
	automaton := ac.NewAutomaton()

	// 从数据库加载敏感词并构建AC自动机
	words, err := db.GetAllSensitiveWords()
	if err != nil {
		log.Fatalf("加载敏感词失败: %v", err)
	}
	for _, word := range words {
		automaton.Insert(word.BadWord)
	}
	automaton.BuildFailureLinks()

	// 创建API处理器
	filterHandler := api.NewFilterHandler(automaton)
	segmentHandler := api.NewSegmentHandler()

	// 注册路由
	http.Handle("/api/filter", filterHandler)
	http.Handle("/api/segment", segmentHandler)

	// 启动HTTP服务
	go func() {
		addr := fmt.Sprintf(":%d", config.Server.Port)
		log.Printf("HTTP服务已启动，监听端口: %d\n", config.Server.Port)
		if err := http.ListenAndServe(addr, nil); err != nil {
			log.Fatalf("HTTP服务启动失败: %v", err)
		}
	}()

	// 定时更新敏感词库
	ticker := time.NewTicker(time.Duration(config.Server.UpdateInterval) * time.Second)
	defer ticker.Stop()

	// 创建信号通道
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	fmt.Printf("服务已启动，监听端口: %d\n", config.Server.Port)

	// 处理定时更新和信号
	for {
		select {
		case <-ticker.C:
			// 更新敏感词库
			words, err := db.GetAllSensitiveWords()
			if err != nil {
				log.Printf("更新敏感词库失败: %v\n", err)
				continue
			}
			// 重建AC自动机
			newAutomaton := ac.NewAutomaton()
			for _, word := range words {
				newAutomaton.Insert(word.BadWord)
			}
			newAutomaton.BuildFailureLinks()
			// 更新缓存
			if err := redis.CacheSensitiveWords(words); err != nil {
				log.Printf("更新Redis缓存失败: %v\n", err)
			}
			log.Println("敏感词库更新完成")
		case sig := <-sigChan:
			fmt.Printf("收到信号: %v，正在关闭服务...\n", sig)
			return
		}
	}
}
